home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / communic / pcmail / main / unalias.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  5.1 KB  |  375 lines

  1. /*++
  2.  
  3. /* NAME
  4.  
  5. /*    unalias 3
  6.  
  7. /* SUMMARY
  8.  
  9. /*    alias processing
  10.  
  11. /* PROJECT
  12.  
  13. /*    pc-mail
  14.  
  15. /* PACKAGE
  16.  
  17. /*    smail
  18.  
  19. /* SYNOPSIS
  20.  
  21. /*    char **unalias(namevec)
  22.  
  23. /*    char **namevec;
  24.  
  25. /* DESCRIPTION
  26.  
  27. /*    unalias() takes an array of string pointers and returns a vector
  28.  
  29. /*    with string pointers to their alias expansions. The resulting
  30.  
  31. /*    vector is in static memory.
  32.  
  33. /*
  34.  
  35. /*    After alias expansion, all addresses are sorted and duplicate
  36.  
  37. /*    names are eliminated. The algorithms for alias expansion and
  38.  
  39. /*    duplicate elimination are case-insensitive.
  40.  
  41. /*
  42.  
  43. /*    unalias() accesses the alias data base through the ascf ASCII
  44.  
  45. /*    filter.
  46.  
  47. /* DIAGNOSTICS
  48.  
  49. /*    unalias() returns a null pointer in case of memory-allocation problems.
  50.  
  51. /*
  52.  
  53. /*    unalias() terminates prematurely when the alias expansion has
  54.  
  55. /*    produced BUFSIZ recipients. This provides some defense against
  56.  
  57. /*    cycles in the alias data base. It is up to the caller to
  58.  
  59. /*    recognize this condition.
  60.  
  61. /* BUGS
  62.  
  63. /*    The overflow/cycle detection algorithm is inelegant.
  64.  
  65. /* FILES
  66.  
  67. /*    Alias data base in spool directory
  68.  
  69. /* AUTHOR(S)
  70.  
  71. /*      W.Z. Venema
  72.  
  73. /*      Eindhoven University of Technology
  74.  
  75. /*      Department of Mathematics and Computer Science
  76.  
  77. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  78.  
  79. /* CREATION DATE
  80.  
  81. /*    Wed Apr  6 20:21:35 MET 1988
  82.  
  83. /* LAST MODIFICATION
  84.  
  85. /*    90/01/22 13:02:54
  86.  
  87. /* VERSION/RELEASE
  88.  
  89. /*    2.1
  90.  
  91. /*--*/
  92.  
  93.  
  94.  
  95. #include "defs.h"
  96.  
  97. #include "hsearch.h"
  98.  
  99. #include "path.h"
  100.  
  101. #include "ascf.h"
  102.  
  103.  
  104.  
  105. /* forward declarations */
  106.  
  107.  
  108.  
  109. hidden int hash_alias();
  110.  
  111. hidden void sort_alias();
  112.  
  113. hidden void uniq_alias();
  114.  
  115. hidden char **find_alias();
  116.  
  117.  
  118.  
  119. /* unalias - replace aliases by their equivalents */
  120.  
  121.  
  122.  
  123. public char **unalias(names)
  124.  
  125. char  **names;
  126.  
  127. {
  128.  
  129.     static int dohash = 1;        /* hash table not yet made */
  130.  
  131.     static char *recp[BUFSIZ + 1];    /* the result of alias expansion */
  132.  
  133.     char  **stop = recp + BUFSIZ;    /* overflow limit */
  134.  
  135.  
  136.  
  137.     if (dohash && (dohash = hash_alias()))    /* build the hash table */
  138.  
  139.     return (0);
  140.  
  141.     if (stop > find_alias(names, recp, stop)) {    /* build vector of addresses */
  142.  
  143.     sort_alias(recp);            /* sort the recp list */
  144.  
  145.     uniq_alias(recp);            /* eliminate duplicates */
  146.  
  147.     }
  148.  
  149.     return (recp);
  150.  
  151. }
  152.  
  153.  
  154.  
  155. /* hash_alias - copy alias data base to hash table */
  156.  
  157.  
  158.  
  159. hidden int hash_alias()
  160.  
  161. {
  162.  
  163.     register FILE *fp;
  164.  
  165.     char    buf[BUFSIZ];
  166.  
  167.  
  168.  
  169.     /* initialize the hash table */
  170.  
  171.  
  172.  
  173.     if (hcreate(BUFSIZ) == 0)
  174.  
  175.     return (-1);
  176.  
  177.  
  178.  
  179.     /*
  180.  
  181.      * Lines in the alias data base are of the form
  182.  
  183.      * 
  184.  
  185.      * <left-hand part>    <right-hand part>
  186.  
  187.      * 
  188.  
  189.      * where the l.h. part is an alias, and the r.h. part one or more words. Of
  190.  
  191.      * course, those words can be aliases. The order in which aliases are
  192.  
  193.      * defined is not important. The alias data base is used only after it
  194.  
  195.      * has been loaded into memory.
  196.  
  197.      * 
  198.  
  199.      * Each l.h. part is used as the key for finding the r.h. part in the hash
  200.  
  201.      * table. The r.h. part is stored as a vector of pointers to strings.
  202.  
  203.      */
  204.  
  205.  
  206.  
  207.     if (fp = ascopen(aliases(), "r")) {        /* read through ASCII filter */
  208.  
  209.     while (ascgets(buf, sizeof(buf), fp)) {    /* read entry from alias file */
  210.  
  211.         register char **cpp;
  212.  
  213.         ENTRY   e;
  214.  
  215.  
  216.  
  217.         if ((cpp = strvec(buf, ", \t\r\n")) == 0)    /* split alias entry */
  218.  
  219.         return (-1);
  220.  
  221.         if ((e.key = *cpp)            /* left-hand part exists */
  222.  
  223.         &&(e.data = (char *) (cpp + 1))    /* right-hand part exists */
  224.  
  225.         &&(hsearch(e, ENTER) == 0))        /* enter hash table */
  226.  
  227.         return (-1);
  228.  
  229.     }
  230.  
  231.     ascclose(fp);
  232.  
  233.     }
  234.  
  235.     return (0);
  236.  
  237. }
  238.  
  239.  
  240.  
  241. /* find_alias - recursively expand aliases */
  242.  
  243.  
  244.  
  245. hidden char **find_alias(from, to, stop)
  246.  
  247. char  **from;
  248.  
  249. register char **to;
  250.  
  251. register char **stop;
  252.  
  253. {
  254.  
  255.     register char **cpp;
  256.  
  257.     register ENTRY *sp;
  258.  
  259.     ENTRY   e;
  260.  
  261.  
  262.  
  263.     /* recursively replace aliases, but don't crash in case of cycles */
  264.  
  265.  
  266.  
  267.     for (cpp = from; *cpp && (to < stop); cpp++) {
  268.  
  269.     e.key = *cpp;
  270.  
  271.     if (sp = hsearch(e, FIND)) {
  272.  
  273.         to = find_alias((char **) sp->data, to, stop);
  274.  
  275.     } else {
  276.  
  277.         *to++ = *cpp;
  278.  
  279.     }
  280.  
  281.     }
  282.  
  283.     *to = 0;
  284.  
  285.     return (to);
  286.  
  287. }
  288.  
  289.  
  290.  
  291. /* Istrcmp - interface between qsort and istrcmp */
  292.  
  293.  
  294.  
  295. hidden int Istrcmp(p1, p2)
  296.  
  297. char  **p1,
  298.  
  299.       **p2;
  300.  
  301. {
  302.  
  303.     return (istrcmp(*p1, *p2));
  304.  
  305. }
  306.  
  307.  
  308.  
  309. /* sort_alias - sort the addresses after alias substitutions */
  310.  
  311.  
  312.  
  313. hidden void sort_alias(to)
  314.  
  315. char  **to;
  316.  
  317. {
  318.  
  319.     register char **cpp;
  320.  
  321.     int     istrcmp();
  322.  
  323.  
  324.  
  325.     /* find out length of the list */
  326.  
  327.  
  328.  
  329.     for (cpp = to; *cpp; cpp++)
  330.  
  331.      /* void */ ;
  332.  
  333.  
  334.  
  335.     /* sort the list */
  336.  
  337.  
  338.  
  339.     qsort((char *) to, cpp - to, sizeof(*to), Istrcmp);
  340.  
  341. }
  342.  
  343.  
  344.  
  345. /* uniq_alias - collapse sequences of identical addresses */
  346.  
  347.  
  348.  
  349. hidden void uniq_alias(to)
  350.  
  351. char  **to;
  352.  
  353. {
  354.  
  355.     register char **in = to;
  356.  
  357.     register char **out = to;
  358.  
  359.  
  360.  
  361.     while (*out = *in) {
  362.  
  363.     while (*++in && istrcmp(*out, *in) == 0) {
  364.  
  365.          /* void */ ;
  366.  
  367.     }
  368.  
  369.     ++out;
  370.  
  371.     }
  372.  
  373. }
  374.  
  375.